<script lang="ts" setup>
  import { PropType,reactive,ref,computed,nextTick,watch,onMounted } from 'vue'
  import { propTypes } from '@/utils/propTypes'
  import { ElTable } from 'element-plus'
  import eAdvancedFilter from '@/components/eAdvancedFilter/src/eAdvancedFilter.vue'
  import Sortable from 'sortablejs'
  import { useAdvancedFilter } from '@/components/eAdvancedFilter/src/type'
  import { Column, TableState } from './type'
  import eTableSettingDialog from './eTableSettingDialog.vue'
  import { thousand } from '@/utils'
  defineOptions({ name: 'CustomTable' })

  // Props 定义
  const props = defineProps({
    selection: propTypes.bool.def(false), // 是否显示选择列
    index: propTypes.bool.def(false), // 是否显示序号列
    modelValue: propTypes.bool.def(false), // 是否显示弹窗
    loading: propTypes.bool.def(false), // 是否显示加载中
    title: propTypes.string.def(''), // 表格标题
    canSetting: propTypes.bool.def(false), // 是否可以设置列
    tableData: propTypes.array.def([]), // 表格数据
    borderBottom: propTypes.bool.def(false), // 是否显示表头下边框
    editStatus: propTypes.bool.def(false), // 是否显示编辑状态
    rules: propTypes.object.def({}), // 表单验证规则
    tableHeader: {
      // 表头列配置
      type: Array as PropType<Column[]>,
      default: () => []
    },
    pagination: propTypes.bool.def(true), // 是否显示分页
    pageNo: propTypes.number.def(1), // 当前页码
    pageSize: propTypes.number.def(10), // 每页条数
    total: propTypes.number.def(0), // 总条数
    uniqueKey: propTypes.string.def('') // 系统表格唯一键，用于存储/读取表格配置
  })

  // 添加 emit 定义
  const emit = defineEmits([
    'update:pageNo',
    'update:pageSize',
    'pagination',
    'update:page',
    'update:limit'
  ])

  // 表格状态管理
  const tableState = reactive<TableState>({
    data: [...props.tableData], // 表格数据
    columns: [...props.tableHeader], // 表头列配置
    filteredData: [...props.tableData] // 筛选后的表格数据
  })

  // 表格引用
  const tableRef = ref<InstanceType<typeof ElTable>>()

  // 列配置管理
  const columnConfig = reactive({
    showDialog: false, // 弹窗是否显示
    configData: [] as Column[], // 全量列表配置数据
    dialogConfigData: [] as Column[], // 弹窗列配置数据
    showColumnOrder: [] as string[], // 显示列顺序
    columnOrder: [] as string[] // 列顺序
  })
  // 监听表格数据变化
  watch(
    () => props.tableData,
    (newData) => {
      tableState.data = [...newData]
      tableState.filteredData = [...newData] // Update filtered data as well
    }
  )
  // 监听表头列配置变化
  watch(
    () => props.tableHeader,
    (newData) => {
      tableState.columns = [...newData]
      initVisibleColumns()
    }
  )

  // 列配置管理
  // 初始化列配置
  const init = () => {
    // 初始化列配置及顺序
    initVisibleColumns()
    // 仅针对可显示表头进行排序
    nextTick(() => initSortable())
  }

  // 表格是否固定项
  const isFixed = computed(() => {
    return columnConfig.configData.some((item) => item.fixType)
  })

  // 获取表格配置
  const getTableConfig = async (): Promise<Column[]> => {
    let config: Column[] = await new Promise((resolve) => {
      setTimeout(() => {
        resolve(JSON.parse(sessionStorage.getItem(props.uniqueKey) || '[]'))
        // resolve(props.tableHeader)
      }, 200)
    })
    return config
  }

  // 根据组件入参初始化列配置
  const initVisibleColumns = async () => {
    // 获取表格配置
    let config: Column[] = []
    if (props.uniqueKey) {
      config = await getTableConfig()
    }
    const configProps = {}
    config.forEach((col, index) => {
      col.sortNo = index
      configProps[col.prop] = col
    })
    // 初始化列配置
    columnConfig.configData = props.tableHeader
      .map((col) => {
        if (configProps[col.prop]) {
          col.show = configProps[col.prop].show
          col.sortNo = configProps[col.prop].sortNo
        } else {
          col.show = true
          col.sortNo = col.sortNo ?? -1
        }
        return col
      })
      .sort((a: Column, b: Column) => {
        return (a.sortNo ?? 0) - (b.sortNo ?? 0)
      })
    console.log('columnConfig.configData', props.uniqueKey, columnConfig.configData)
    // 初始化列表顺序
    columnConfig.columnOrder = getColumnOrder(columnConfig.configData)
  }

  // 初始化表格列顺序
  const getColumnOrder = (data: any[]) => {
    const leftFixedColumns = data
      .filter((col) => col.prop && col.show && col.fixType === 'left')
      .map((col) => col.prop)

    const normalColumns = data
      .filter((col) => col.prop && col.show && !col.fixType)
      .map((col) => col.prop)

    const rightFixedColumns = data
      .filter((col) => col.prop && col.show && col.fixType === 'right')
      .map((col) => col.prop)

    return [...leftFixedColumns, ...normalColumns, ...rightFixedColumns]
  }

  const {
    tableFilters,
    advancedFilterRefs,
    openAdvancedFilter,
    clearFilter,
    handleAdvancedFilterChange
  } = useAdvancedFilter()

  // 高级筛选管理
  const handleFilterChange = (filters: any) => {
    handleAdvancedFilterChange(filters, true)
    tableState.filteredData = [...tableState.data]

    Object.values(tableFilters.value).forEach((filter: any) => {
      if (
        Array.isArray(filter.include) &&
        filter.include.some((item) => item.value || item.value === 0)
      ) {
        applyIncludeFilter(filter)
      }
      if (filter.exclude?.length > 0) {
        applyExcludeFilter(filter)
      }
    })
  }

  // 应用包含过滤
  const applyIncludeFilter = (filter: any) => {
    tableState.filteredData = tableState.filteredData.filter((item) => {
      const value = item[filter.field]
      return filter.include.some((condition: any) => {
        const conditionValue = getConditionValue(condition)
        return evaluateCondition(value, condition.operator, conditionValue)
      })
    })
  }

  // 应用排除过滤
  const applyExcludeFilter = (filter: any) => {
    tableState.filteredData = tableState.filteredData.filter((item) => {
      return !filter.exclude.some((condition: any) => {
        const value = Number(item[filter.field])
        const conditionValue = getConditionValue(condition)
        return evaluateCondition(value, condition.operator, conditionValue)
      })
    })
  }

  // 获取条件值
  const getConditionValue = (condition: any) => {
    return condition.operator === 'range' || condition.operator === 'not_range'
      ? [Number(condition.value[0]), Number(condition.value[1])]
      : condition.value
  }

  // 评估条件
  const evaluateCondition = (value: any, operator: string, conditionValue: any) => {
    switch (operator) {
      case 'eq':
        return value == conditionValue
      case 'neq':
        return value != conditionValue
      case 'gt':
        return value > conditionValue
      case 'gte':
        return value >= conditionValue
      case 'lt':
        return value < conditionValue
      case 'lte':
        return value <= conditionValue
      case 'range':
        return value >= conditionValue[0] && value <= conditionValue[1]
      case 'not_range':
        return value < conditionValue[0] || value > conditionValue[1]
      case 'like':
        const pattern = conditionValue.replace(/\*/g, '.*')
        return new RegExp(`^${pattern}$`).test(String(value))
      default:
        return true
    }
  }

  /**
   * 初始化表格拖拽排序功能
   */
  function initSortable() {
    const el = tableRef.value?.$el.querySelector('.el-table__header-wrapper thead tr')
    if (!el) return

    Sortable.create(el, {
      animation: 300, // 动画时长
      handle: '.draggable-column', // 拖拽元素选择器
      ghostClass: 'sortable-ghost', // 拖动时的样式
      dragClass: 'sortable-drag', // 拖动时的样式
      draggable: '.draggable-column', // 可拖拽的元素
      filter: '.el-table-fixed-column--left,.el-table-fixed-column--right', // 过滤元素
      onMove: function (evt) {
        // 如果目标元素包含 el-table-fixed-column--left， el-table-fixed-column--right 类，则阻止移动
        return (
          !evt.related.classList.contains('el-table-fixed-column--left') &&
          !evt.related.classList.contains('el-table-fixed-column--right')
        )
      },
      onEnd: ({ newIndex, oldIndex }) => {
        if (newIndex === undefined || oldIndex === undefined) return
        let len = 0
        if (props.selection) len++
        if (props.index) len++

        // 需要考虑选择列和序号列的偏移
        const realOldIndex = oldIndex - len // 减去选择列和序号列
        const realNewIndex = newIndex - len

        // 更新列顺序
        const newOrder = [...columnConfig.columnOrder]
        const [moved] = newOrder.splice(realOldIndex, 1)
        newOrder.splice(realNewIndex, 0, moved)
        columnConfig.columnOrder = newOrder // 表格数据根据排序顺序重新计算列表项
      }
    })
  }

  // 计算排序后的列
  const sortedColumns = computed(() => {
    // 获取所有可见列
    const visibleColumns = columnConfig.configData.filter((item) => item.show)

    // 如果没有自定义顺序，返回所有可见列
    if (columnConfig.columnOrder.length === 0) {
      return visibleColumns
    }

    // 创建一个新的排序后的列数组
    const orderedColumns: Column[] = []

    // 首先添加已在 columnOrder 中的可见列，按照 columnOrder 的顺序排序
    columnConfig.columnOrder.forEach((prop) => {
      const column = visibleColumns.find((col) => col.prop === prop)
      if (column && column.show) {
        orderedColumns.push(column)
      }
    })

    // 添加未在 columnOrder 中的可见列
    visibleColumns.forEach((column) => {
      if (!columnConfig.columnOrder.includes(column.prop)) {
        orderedColumns.push(column)
      }
    })

    return orderedColumns
  })

  // 生命周期钩子
  onMounted(() => {
    init()
  })

  const tableSettingDialogRef = ref()
  // 打开列设置弹窗
  const openDialog = () => {
    tableSettingDialogRef.value.openDialog(props.tableHeader)
  }

  // 应用列设置
  const handleApplyColumns = (newConfigData: Column[]) => {
    // 保存列表设置到本地
    if (props.uniqueKey) {
      sessionStorage.setItem(props.uniqueKey, JSON.stringify(newConfigData))
    }
    // 更新列表设置
    columnConfig.columnOrder = getColumnOrder(newConfigData)
    columnConfig.configData = newConfigData
  }
  const pageSize = computed({
    get() {
      return props.pageSize
    },
    set(val) {
      emit('update:pageSize', val)
    }
  })
  const pageNo = computed({
    get() {
      return props.pageNo
    },
    set(val) {
      console.log('pageNo', val)
      emit('update:pageNo', val)
    }
  })
</script>

<template>
  <el-card class="card-table">
    <slot name="title">
      <div class="table-title" :class="{ 'border-bottom': borderBottom }">
        <div class="flex items-center">
          <slot name="custom-title">
            <span class="table-title-text">{{ title || '查询结果' }}</span>
          </slot>
        </div>
        <div class="flex items-center">
          <slot name="custom-btn"> </slot>
          <e-button @click="openDialog" v-if="canSetting" class="ml-2">
            <Icon :size="16" icon="ep:setting" /> 高级筛选
          </e-button>
        </div>
      </div>
    </slot>
    <div class="table-body">
      <el-form ref="formTableRef" :model="tableData" :rules="rules">
        <el-table
          ref="tableRef"
          class="custom-table"
          :data="tableState.filteredData"
          v-bind="$attrs"
        >
          <!-- 选择列 -->
          <el-table-column type="selection" :fixed="isFixed" v-if="selection" width="55" />
          <!-- 序号列 -->
          <el-table-column type="index" label="序号" :fixed="isFixed" v-if="index" width="55" />
          <!-- 数据列 -->
          <el-table-column
            v-for="column in sortedColumns"
            :key="column.prop"
            :prop="column.prop"
            :label="column.label"
            :sortable="column.sortable"
            class-name="draggable-column"
            :align="column.alignType"
            :header-align="column.headerAlign || column.alignType"
            :fixed="column.fixType || undefined"
            :width="column.width"
          >
            <template #header>
              <slot :name="`header-${column.prop}`" :column="column">
                <div class="table-header-container">
                  <span>
                    <span v-if="column.required" class="required-icon">*</span>
                    {{ column.label }}
                  </span>
                  <template v-if="column.filterConfig">
                    <Icon
                      @click.stop="openAdvancedFilter(column.prop + 'table')"
                      icon="ep:filter"
                    />
                    <eAdvancedFilter
                      :ref="(el) => (advancedFilterRefs[column.prop + 'table'] = el)"
                      :title="`${column.label}高级筛选`"
                      :filterConfig="column.filterConfig"
                      :field="column.prop"
                      @filter-change="handleFilterChange"
                      @clear-filter="clearFilter"
                    />
                  </template>
                </div>
              </slot>
            </template>
            <template #default="scope">
              <slot :name="column.prop" :row="scope.row" :index="scope['$index']">
                <el-form-item
                  v-if="editStatus && column.filterConfig?.type === 'input'"
                  :prop="`${scope.$index}.${column.prop}`"
                  :rules="rules[column.prop]"
                >
                  <el-input
                    v-model="scope.row[column.prop]"
                    :placeholder="column.filterConfig.placeholder"
                  />
                </el-form-item>
                <el-form-item
                  v-else-if="editStatus && column.filterConfig?.type === 'select'"
                  :prop="`${scope.$index}.${column.prop}`"
                  :rules="rules[column.prop]"
                >
                  <el-select
                    v-model="scope.row[column.prop]"
                    :placeholder="column.filterConfig.placeholder"
                  >
                    <el-option
                      v-for="item in column.filterConfig.options"
                      :key="item.value"
                      :label="item.label"
                      :value="item.value"
                    />
                  </el-select>
                </el-form-item>

                <el-form-item v-else-if="editStatus && column.filterConfig?.type === 'date'">
                  <el-date-picker
                    v-model="scope.row[column.prop]"
                    class="value-input"
                    format="YYYY-MM-DD"
                    value-format="YYYY-MM-DD"
                    :placeholder="column.filterConfig.placeholder"
                  />
                </el-form-item>
                <el-form-item v-else-if="editStatus && column.filterConfig?.type === 'dateRange'">
                  <el-date-picker
                    v-model="scope.row[column.prop]"
                    class="value-input"
                    type="daterange"
                    format="YYYY-MM-DD"
                    value-format="YYYY-MM-DD"
                    range-separator="To"
                    start-placeholder="Start date"
                    end-placeholder="End date"
                    :placeholder="column.filterConfig.placeholder"
                  />
                </el-form-item>
                <template v-else>
                  {{
                    column.filterConfig?.needThousand
                      ? thousand(scope.row[column.prop])
                      : scope.row[column.prop]
                  }}
                </template>
              </slot>
            </template>
          </el-table-column>
        </el-table>
      </el-form>
      <Pagination
        v-if="props.pagination"
        v-model:limit="pageSize"
        v-model:page="pageNo"
        :total="props.total"
        @pagination="(obj) => emit('pagination', obj)"
      />
    </div>
  </el-card>

  <!-- 列设置弹窗 -->
  <eTableSettingDialog
    ref="tableSettingDialogRef"
    :config-data="columnConfig.configData"
    @apply="handleApplyColumns"
  />
</template>

<style lang="scss" scoped>
  .card-table {
    :deep(.el-card__body) {
      padding: 0px;
    }
  }
  .table-title {
    display: flex;
    justify-content: space-between;
    align-items: center;
    color: #000000;
    height: 56px;
    line-height: 56px;
    padding: 0 20px;
    .table-title-text {
      font-family: PingFang SC;
      font-size: 18px;
      font-weight: 600;
      line-height: 25.2px;
      text-align: left;
      text-underline-position: from-font;
      text-decoration-skip-ink: none;
      color: #000000;
    }
  }
  .table-body {
    padding: 0 20px 20px;
  }
  .border-bottom {
    border-bottom: 1px solid #cccccc;
    margin-bottom: 20px;
  }
  :deep(.custom-table) {
    .el-table__header {
      .required-icon {
        color: red;
      }
      .cell {
        display: flex;
        align-items: center;
        .table-header-container {
          display: inline-flex;
          flex: 1;
          align-items: center;
          justify-content: space-between;
        }
      }
    }
  }
  // :deep(.el-button.is-text) {
  //   padding: 8px 4px;
  //   margin-left: 0;
  // }

  :deep(.sortable-ghost) {
    opacity: 0.5;
    background: #a8abb2;
  }

  :deep(.el-table__row) {
    .el-table__cell {
      padding: 0;
      height: 40px;
      line-height: 40px;
    }
    .el-form-item {
      width: 100%;
      margin-bottom: 0;
      margin-right: 0;
    }
  }
</style>
